/*
 * article.cpp
 *
 *  Created on: Jan 31, 2012
 *      Author: mostafa
 */
#include "article.h"
#include <fstream>
#include <iostream>
#include "XMLFormatter.h"

#include <list>
#include "maxent.h"
using  namespace std;

extern void tokenize(const string & s1, list<string> & lt);

extern ME_Sample NER_mesample(const string & label, const vector<Token> &vt, int begin, int end);

extern void find_NEs(const ME_Model & me,Sentence & s);
extern void
bidir_decode_beam(vector<Token> & vt,
		const multimap<string, string> & tag_dictionary,
		const vector<ME_Model> & vme);
void stemSentence(Sentence *s);
extern void bidir_chunking(vector<Sentence> & vs, const vector<ME_Model> & vme);

void
bidir_chuning_decode_beam(vector<Token> & vt,
		const vector<ME_Model> & vme);





article::article() {
	//	extern void split(string text,string delmiter,vector<string>* result);
	//	extern string intToString(int x);
	//	extern void split(const string& s, char c,vector<string>& v);
	// TODO Auto-generated constructor stub
	score=0;
}

void article::writetoXml(string Path)
{
	string xml_base="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<?xml-stylesheet type=\"text/css\" href=\"gpml.css\" ?>\n<!DOCTYPE set SYSTEM \"gpml.dtd\">\n";
	// Save in file
	ofstream File((Path+PumbedID).c_str(), ios::out);
	XMLFormatter x;// Object from XMLFormatter Class
	// string that contains the article info body
	// at every field in article info I check if this field is empty "doesn't exists"
	// put an empty line
	string xml_articleinfo = "" ;
	if(this->PumbedID == "")
		xml_articleinfo = "";
	else
		xml_articleinfo =  x.Formatter(x.bibliomisc,"MEDLINE:"+this->PumbedID,NULL);
	//save the xml_base and article info
	File<< xml_base;
	File<<"<article>"<<endl;
	// the year of publish if not exists so put empty line otherwise print the year
	if(this->year == NULL)
		xml_articleinfo += "";
	else
		xml_articleinfo += x.Formatter(x.year,intToString(this->year),NULL);
	// the score of paper if not exists so put empty line otherwise print the score
	if(this->score == NULL)
		xml_articleinfo += "";
	else
		xml_articleinfo+= x.Formatter(x.score,intToString(this->score) , NULL);
	// the affilation of paper if not exists so put empty line otherwise print the affiation
	if(this->affilation == "")
		xml_articleinfo +="";
	else
		xml_articleinfo += x.Formatter(x.affilation,this->affilation,NULL);
	// the name of the author(s) if not exists so put empty line otherwise print the author(s)
	if(this->authors == "")
		xml_articleinfo += "";
	else
		xml_articleinfo += x.Formatter(x.authors,this->authors, NULL);

	if(this->title == "")
		xml_articleinfo += "";
	else
		xml_articleinfo += x.Formatter(x.title,this->title, NULL);
	// at the end of info put all of this is article info tag
	xml_articleinfo=x.Formatter(x.articleinfo,xml_articleinfo,NULL);
	// end of article info and finally save all info in file
	File << xml_articleinfo;
	testing=xml_articleinfo;
	string xml_abstract="";
	for(int i=0;i<abstract.size();i++)
	{
		//start the sentence tag and cons tag
		string sentence="";
		//if the sentence tags has no parameters so open sentence tag and close it otherwise open cons for every word belongs to defined class
		//		for(int j=0;j<abstract[i]->size();j++)
		//		{
		//			if(abstract[i]->at(j).ne.compare("O")!=0)
		//				abstract[i]->at(j).ne=abstract[i]->at(j).ne.substr(2,abstract[i]->at(j).ne.size()-2);
		//
		//		}
		for(int j=0;j<abstract[i]->size();j++)
		{
			string temp=abstract[i]->at(j).str;

			if(abstract[i]->at(j).ne.compare("")&&abstract[i]->at(j).ne.compare("O")!=0)
			{
				// define a vector to push the cons tags in this
				vector<string> attr;
				attr.clear();
				string temp2;
				temp2+="sem=";
				temp2+="\"";
				temp2+=abstract[i]->at(j).ne;
				temp2+="\"";
				int beginindex=j;

				//if the 2 cons belongs to the same class put this words in the same cons tag
				while(j+1<abstract[i]->size()&&(abstract[i]->at(j+1).ne.compare(abstract[i]->at(beginindex).ne)==0))
				{
					temp+=" "+abstract[i]->at(j+1).str;
					j++;
				}
				attr.push_back(temp2);
				temp=x.Formatter(x.cons,temp,&attr);
			}
			sentence+=temp+" ";
		}
		// if there is no sentence put empty line otherwise print the tag

		if(sentence.compare("")==0)
			xml_abstract += "";
		else
		{
			//		cout<<sentence<<endl;
			xml_abstract+=x.Formatter(x.sentence,sentence,NULL)+"\n";
		}
	}

	xml_abstract=x.Formatter(x.abstract_,xml_abstract,NULL);
	//cout<<xml_abstract<<endl;
	testing+=xml_abstract;
	File <<xml_abstract;
	File<<"</article>"<<endl;
	File.close();
	//delete &x;
}
bool endofsentence(list<string>::iterator it)
{
	string notendofsentence[3]={"etc.","i.e.","e.g."};
	for(int i=0;i<3;i++)
		if(it->compare(notendofsentence[i])==0)
			return false;
	if(it->at(it->size()-1)=='.'&&it->size()!=1)
	{
		return true;
	}
	return false;

}
bool article::readfromPubmedxml(string Path)
{
	XMLFormatter *my_x;
	vector <string> Allstrings;
	try{
		my_x  = new XMLFormatter();
		ifstream inFile;
		int my_Counter = 0;
		string line1;
		string myline;

		vector <string> res;
		Allstrings.clear();
		res.clear();
		abstract.clear();
		int counter = 0;
		//	cout<<Path<<endl;
		// open a file with the given path
		inFile.open( Path.c_str() );
		if ( !inFile.is_open() )
		{
			//	cleanvector(&Allstrings);
			delete my_x;
			cout<<"can not open this file"<<endl;
			return -1;
		}
		// read to the end of the file
		while ( !inFile.eof() )
		{
			getline(inFile,line1);
			myline+=line1;
		}
		inFile.close();
		//get specific data from the file
		int result=0;
		// set the id number
		result=result|my_x->getStrings(my_x->Pubmed_id,myline,&Allstrings,&res);
		if(Allstrings.size()>0)
		{
			setPumbedId(Allstrings.back());
			//cout<<getPumbedId()<<endl;
		}
		cleanvector(&Allstrings);
		my_Counter++;
		// set the year
		result=result|my_x->getStrings(my_x->Pubmed_date,myline,&Allstrings,&res);
		if(Allstrings.size()>0)
		{
			string temp=Allstrings.back();
			Allstrings.clear();
			result=result|my_x->getStrings(my_x->Pubmed_year,temp,&Allstrings,&res);
			if(result==0)
			{
				if(Allstrings.size()>0)
				{
					setYear(atoi(Allstrings.back().c_str()));
					//		cout<<getYear()<<endl;
				}
			}
		}
		cleanvector(&Allstrings);
		my_Counter++;
		//set the title
		result=result|my_x->getStrings(my_x->Pubmed_title,myline,&Allstrings,&res);
		if(result!=0)
		{
			//		cleanvector(&Allstrings);
			delete my_x;
			cout<<"error in xml"<<endl;
			return -2;
		}
		if(Allstrings.size()>0)
		{
			setTitle(Allstrings.back());
			//cout<<getTitle()<<endl;
		}
		my_Counter++;
		Allstrings.clear();
		cleanvector(&Allstrings);
		// set the sentence and each cons in it fron the abstract
		//my_x->getStrings(my_x->abstract_,myline,&Allstrings,&res);
		result=result|my_x->getStrings(my_x->Pubmed_abstract,myline,&Allstrings,&res);
		for(int i=0;i<Allstrings.size();i++)
		{
			list<string> words;
			tokenize(Allstrings[i],words);
			list<string>::iterator it=words.begin();
			Sentence * curr=new Sentence();
			while(it!=words.end())
			{
				if(endofsentence(it))
				{
					Token *m=new Token(*it,"");
					m->ne="O";
					curr->push_back(*(m));
					abstract.push_back(curr);
					curr=new Sentence();
					delete m;
				}
				else
				{
					//	cout<<*it<<endl;
					Token *m=new Token(*it,"");
					m->ne="O";
					curr->push_back(*(m));
					delete m;
				}
				it++;
			}
			abstract.push_back(curr);
		}
		cleanvector(&Allstrings);
		delete my_x;
		//check();
		//PrintAbstract();
		return 0;
	}
	catch(exception &e)
	{
		cleanvector(&Allstrings);
		delete my_x;
		return false;
	}
}

void article::writetoHTML(string Path)
{
	string xml_base="<html>\n<head>\n<link href=\"NLP-EGY.css\" rel=\"stylesheet\" type=\"text/css\" />\n</head>\n<body>\n";
	// Save in file
	ofstream File((Path+PumbedID).c_str(), ios::out);
	XMLFormatter x;// Object from XMLFormatter Class
	// string that contains the article info body
	// at every field in article info I check if this field is empty "doesn't exists"
	// put an empty line
	string xml_articleinfo = "" ;
	if(this->PumbedID == "")
		xml_articleinfo = "";
	else
		xml_articleinfo =  x.Formatter(x.bibliomisc,"MEDLINE:"+this->PumbedID,NULL);
	//save the xml_base and article info
	File<< xml_base;
	File<<"<article>"<<endl;
	// the year of publish if not exists so put empty line otherwise print the year
	if(this->year == NULL)
		xml_articleinfo += "";
	else
		xml_articleinfo += x.Formatter(x.year,intToString(this->year),NULL);
	// the score of paper if not exists so put empty line otherwise print the score
	if(this->score == NULL)
		xml_articleinfo += "";
	else
		xml_articleinfo+= x.Formatter(x.score,intToString(this->score) , NULL);
	// the affilation of paper if not exists so put empty line otherwise print the affiation
	if(this->affilation == "")
		xml_articleinfo +="";
	else
		xml_articleinfo += x.Formatter(x.affilation,this->affilation,NULL);
	// the name of the author(s) if not exists so put empty line otherwise print the author(s)
	if(this->authors == "")
		xml_articleinfo += "";
	else
		xml_articleinfo += x.Formatter(x.authors,this->authors, NULL);

	if(this->title == "")
		xml_articleinfo += "";
	else
		xml_articleinfo += x.Formatter(x.title,this->title, NULL);
	// at the end of info put all of this is article info tag
	xml_articleinfo=x.Formatter(x.articleinfo,xml_articleinfo,NULL);
	// end of article info and finally save all info in file
	File << xml_articleinfo;
	testing=xml_articleinfo;
	string xml_abstract="";
	for(int i=0;i<abstract.size();i++)
	{
		//start the sentence tag and cons tag
		string sentence="";
		//if the sentence tags has no parameters so open sentence tag and close it otherwise open cons for every word belongs to defined class
		for(int j=0;j<abstract[i]->size();j++)
		{
			if(abstract[i]->at(j).ne.compare("O")!=0)
				abstract[i]->at(j).ne=abstract[i]->at(j).ne.substr(2,abstract[i]->at(j).ne.size()-2);

		}
		for(int j=0;j<abstract[i]->size();j++)
		{
			string temp=abstract[i]->at(j).str;

			if(abstract[i]->at(j).ne.compare("")&&abstract[i]->at(j).ne.compare("O")!=0)
			{
				// define a vector to push the cons tags in this
				vector<string> attr;
				attr.clear();
				string temp2;
				temp2+="sem=";
				temp2+="\"";
				temp2+=abstract[i]->at(j).ne;
				temp2+="\"";
				int beginindex=j;

				//if the 2 cons belongs to the same class put this words in the same cons tag
				while(j+1<abstract[i]->size()&&(abstract[i]->at(j+1).ne.compare(abstract[i]->at(beginindex).ne)==0))
				{
					temp+=" "+abstract[i]->at(j+1).str;
					j++;
				}
				attr.push_back(temp2);
				temp=x.Formatter(x.cons,temp,&attr);
			}
			sentence+=temp+" ";
		}
		// if there is no sentence put empty line otherwise print the tag

		if(sentence.compare("")==0)
			xml_abstract += "";
		else
		{
			//        cout<<sentence<<endl;
			xml_abstract+=x.Formatter(x.sentence,sentence,NULL)+"\n";
		}
	}

	xml_abstract=x.Formatter(x.abstract_,xml_abstract,NULL);
	//cout<<xml_abstract<<endl;
	testing+=xml_abstract;
	File <<xml_abstract;
	File<<"</article><br /><br />"<<endl<<endl<<endl;
	File<<"<table width=\"106\" border=\"0\">"<<endl;
	File<<"<tr><td width=\"51\" bgcolor=\"#ccffff\">&nbsp;</td><td width=\"45\">DNA</td></tr>"<<endl;
	File<<"<tr><td bgcolor=\"#FFcccc\">&nbsp;</td><td>other_name</td></tr>"<<endl;
	File<<"<tr><td bgcolor=\"#99fc0f\"></td><td>Protein</td></tr>"<<endl;
	File<<"<tr><td bgcolor=\"#fff000\"></td><td>RNA</td></tr>"<<endl;
	File<<"<tr><td bgcolor=\"#CFC\"></td><td>Disease</td></tr>"<<endl;
	File<<"<tr><td bgcolor=\"#ccff99\"></td><td>Cell_type</td></tr>"<<endl;
	File<<"<tr><td bgcolor=\"#99fAA0\"></td><td>Cell_line</td></tr>"<<endl;
	File<<"<tr><td bgcolor=\"#AAAAAA\"></td><td>Disease</td></tr>"<<endl;
	File<<"<tr><td bgcolor=\"#CC1155\"></td><td>Treatment</td></tr>"<<endl;
	File<<"</table></body></html>"<<endl;
	File.close();
	//delete &x;
}


int article::readfromXml(string Path)
{
	pugi::xml_document doc;
	doc.load_file(Path.c_str());
	readrfomXMl(doc.child("article"));
	return 0;
}
void article::tokenizeSentence(string s,Sentence* sen,string ne)
{
	list<string> tokens;
	tokens.clear();
	tokenize(s, tokens);
	Token * t;
	for (list<string>::const_iterator i = tokens.begin(); i != tokens.end(); i++) {

		t=new Token(*i,"");
		sen->push_back(*(t));
		sen->back().ne=ne;
		delete t;
	}
}

vector<Token> article::getNamed_entities()
{
	vector<Token> namedentities;
	for(int p=0;p<abstract.size();p++)
	{
		string temp="";
		for(int i=0;i<abstract[p]->size();i++)
		{
			if(abstract[p]->at(i).ne.compare("") !=0 && abstract[p]->at(i).ne.compare("O") !=0)
			{
				temp=abstract[p]->at(i).str+" ";
				string ne = abstract[p]->at(i).ne;
				ne=ne.substr(2,(ne.size()-2));
				for(int j=i+1;j<abstract[p]->size();j++)
				{
					string currne=abstract[p]->at(j).ne;
					if(currne.compare("O")!=0)
						currne=currne.substr(2,(currne.size()-2));
					if(currne.compare(ne) == 0)
					{
						i++;
						temp+=abstract[p]->at(j).str+" ";
					}else{
						Token t(temp.substr(0,temp.size()-1),"");

						t.ne=ne;
						//		cout<<t.str<<"  "<<t.ne<<endl;
						namedentities.push_back(t);
						temp="";
						break;
					}
				}
			}
		}
	}
	return namedentities;
}
void article::NLPProcessing(const vector<ME_Model> & vme, const vector<ME_Model> & chunking_vme,const ME_Model & NE)
{
	for(int i=0;i<abstract.size();i++)
	{
		const multimap<string, string> dummy;
		//  bidir_decode_search(vt, dummy, vme);
		bidir_decode_beam(*abstract[i], dummy, vme);
		for (size_t f = 0; f < abstract[i]->size(); f++) {
			abstract[i]->at(f).pos = abstract[i]->at(f).prd;
		}
		bidir_chuning_decode_beam(*abstract[i], chunking_vme);
		Sentence temp;
		//cout<<endl;
		temp.clear();
		for(int j=0;j<abstract[i]->size();j++)
		{
			//	cout<<j<<"\t";
			Token t=Token(abstract[i]->at(j).str,abstract[i]->at(j).pos);
			t.ne="O";
			temp.push_back(t);
		}
		//cout<<endl;
		//	cout<<temp[0].str<<endl;
		find_NEs(NE,temp);

		vector<int> currlengthes;
		vector<string> currne;
		currlengthes.clear();
		currne.clear();

		for(int j=0;j<temp.size();j++)
		{

			if(temp[j].ne.compare("O")!=0)
			{
				int count=1;
				for(int k=j+1;k<temp.size();k++)
				{
					if(temp[k].ne.compare(temp[j].ne)!=0)
						break;
					else
						count++;
				}
				for(int p=0;p<count;p++)
				{
					//				cout<<count<<"\t";
					currlengthes.push_back(count);
					currne.push_back(temp[j].ne);
				}
				j+=count-1;
			}
			else
			{
				///			cout<<"0\t";
				currlengthes.push_back(0);
				currne.push_back("O");
			}
		}
		///	cout<<temp.size()<<" "<<currne.size()<<endl;
		vector<int> prevlenghtes;
		vector<string> prevne;
		prevlenghtes.clear();
		prevne.clear();
		///	cout<<endl;
		for(int j=0;j<abstract[i]->size();j++)
		{

			if(abstract[i]->at(j).ne.compare("O")!=0)
			{
				int count=1;
				for(int k=j+1;k<abstract[i]->size();k++)
				{
					if(abstract[i]->at(j).ne.compare(abstract[i]->at(k).ne)!=0)
						break;
					else
						count++;
				}
				for(int p=0;p<count;p++)
				{
					///		cout<<count<<"\t";
					prevlenghtes.push_back(count);
					prevne.push_back(abstract[i]->at(j).ne);
				}
				j+=count-1;
			}
			else
			{
				//		cout<<"0\t";
				prevlenghtes.push_back(0);
				prevne.push_back("O");
			}
		}
		for(int j=0;j<temp.size();j++)
		{
			if(currlengthes[j]>prevlenghtes[j])
				abstract[i]->at(j).ne=currne[j];
			else
				abstract[i]->at(j).ne=prevne[j];
		}



	}

}

void article::addIOB()
{
	for(int i=0;i<abstract.size();i++)
	{
		bool intag=false;
		for(int j=0;j<abstract[i]->size();j++)
		{
			//	cout<<i<<"   "<<j<<endl;
			if(intag)
			{
				if(abstract[i]->at(j).ne.compare(abstract[i]->at(j-1).ne.substr(2,abstract[i]->at(j-1).ne.size()-2))==0)
				{
					abstract[i]->at(j).ne="I-"+abstract[i]->at(j).ne;
					//		cout<<abstract[i]->at(j).ne<<endl;
				}
				else
				{
					intag=false;
					j--;
				}
			}
			else
			{
				if(abstract[i]->at(j).ne.compare("O")!=0)
				{
					//			cout<<"flag"<<endl;
					abstract[i]->at(j).ne="B-"+abstract[i]->at(j).ne;
					//		cout<<abstract[i]->at(j).ne<<endl;
					intag=true;
				}

			}
		}
	}
}
vector<Relation> article::getRealtions(ME_Model ContainRelation,ME_Model Classify)
{
	Relation R;
	vector<Relation> All_relations;
	for(int i=0;i<abstract.size();i++)
	{
		vector<Relation> temp=R.FindRelations(*abstract[i],ContainRelation,Classify);
		for(int j=0;j<temp.size();j++)
			All_relations.push_back(temp[j]);
	}
	return All_relations;
}


string organizeNE(string NE)
{
	//cout<<"            "<<NE<<endl;
	if(NE.substr(0,2).compare("G#")==0)
		NE=NE.substr(2,NE.size()-2);
	if(NE.substr(0,1).compare("(")==0)
	{
		//cout<<"            "<<NE<<endl;
		int begin=NE.find_last_of("#");
		int last=NE.find_last_of(")");
		NE=NE.substr(begin+1,(last-begin-1));
		//		cout<<"            "<<NE<<endl;
	}

	string protein[8]={"protein","protein_N/A",
			"protein_complex",
			"protein_domain_or_region",
			"protein_family_or_group",
			"protein_molecule",
			"protein_substructure",
			"protein_subunit" };
	string DNA[6]={"DNA","DNA_N/A",
			"DNA_domain_or_region",
			"DNA_family_or_group",
			"DNA_molecule",
			"DNA_substructure"};

	string RNA[6]={"RNA","RNA_N/A",
			"RNA_domain_or_region",
			"RNA_family_or_group",
			"RNA_molecule",
			"RNA_substructure" };

	for(int i=0;i<8;i++)
	{
		if(NE.compare(protein[i])==0)
		{
			NE="protein";
		}
	}
	for(int i=0;i<6;i++)
	{
		if(NE.compare(DNA[i])==0)
		{
			NE="DNA";
		}
	}
	for(int i=0;i<6;i++)
	{
		if(NE.compare(RNA[i])==0)
		{
			NE="RNA";
		}
	}
	//cout<<"            "<<NE<<endl;
	string validentites[5]={"DNA","RNA","protein","cell_line","cell_type"};
	bool valid=false;
	for(int i=0;i<5;i++)
	{
		if(NE.compare(validentites[i])==0)
		{
			valid=true;
		}
	}
	if(!valid)
		NE="O";

	//	cout<<NE<<endl;

	return NE;
}
Sentence article::get_Sentence_from_cons(pugi::xml_node cons)
{
	string con="cons";
	Sentence sen;
	string ne=cons.attribute("sem").as_string();
	//cout<<"   "<<ne<<endl;
	//	if(ne.compare("")!=0)
	//		ne=ne.substr(2,ne.size()-2);
	//	//cout<<"   "<<ne<<endl;
	for(pugi::xml_node child=cons.first_child();child;child=child.next_sibling())
	{
		if(con.compare(child.name())==0)
		{
			Sentence temp=get_Sentence_from_cons(child);
			for(int i=0;i<temp.size();i++)
			{
				temp[i].ne=(ne);
				sen.push_back(temp[i]);
			}
		}
		else
		{
			//	cout<<chnild.text().as_string()<<endl;
			tokenizeSentence(child.text().as_string(),&sen,(ne));
		}
	}
	//cout<<"end flag"<<endl;
	return sen;
}

Sentence article::get_Sentence_from_cons(pugi::xml_node cons,Sentence* sen,vector<int>* begin,vector<int>* end,vector<string>* c)
{
	string con="cons";
	string ne=cons.attribute("sem").as_string();
	//cout<<"   "<<ne<<endl;
	//	if(ne.compare("")!=0)
	//		ne=ne.substr(2,ne.size()-2);
	//	//cout<<"   "<<ne<<endl;
	int tempbegin=sen->size();
	ne=organizeNE(ne);
	for(pugi::xml_node child=cons.first_child();child;child=child.next_sibling())
	{
		if(con.compare(child.name())==0)
		{
			Sentence temp=get_Sentence_from_cons(child,sen,begin,end,c);
		}
		else
		{
			//		cout<<child.attribute("lex").as_string()<<"   "<<organizeNE(ne)<<endl;
			tokenizeSentence(child.text().as_string(),sen,organizeNE(ne));
		}
	}
	begin->push_back(tempbegin);
	end->push_back(sen->size());
	c->push_back(ne);
	//cout<<"end flag"<<endl;
	return *sen;
}


 bool call_is_candidate(const Sentence & s, const int begin, const int end);



vector<ME_Sample> article::getFeaturesfomXMl(pugi::xml_node article,vector<ME_Model>vme,vector<ME_Model>vme_chunking)
{
	string raw_id=article.child("articleinfo").child("bibliomisc").text().as_string();
	string con="cons";

	for(pugi::xml_node title=article.child("title").child("sentence");title;title=title.next_sibling("sentence"))
		article.child("abstract").append_copy(title);

	vector<ME_Sample> result;
	result.clear();
	for(pugi::xml_node sentence=article.child("abstract").child("sentence");sentence;sentence=sentence.next_sibling())
	{
		Sentence* sen=new Sentence();
		vector<int> begin;
		vector<int> end;
		vector<string> ne;
		begin.clear();
		end.clear();
		ne.clear();
		for(pugi::xml_node token=sentence.first_child();token;token=token.next_sibling())
		{
			//		cout<<token.name()<<endl;
			if(con.compare(token.name())==0)
			{
				Sentence temp=get_Sentence_from_cons(token,sen,&begin,&end,&ne);
			}
			else
			{
				//cout<<token.text().as_string()<<endl;
				int begins=sen->size();
				tokenizeSentence(token.text().as_string(),sen,"O");
				int ends=sen->size();
			}
		}


		const multimap<string, string> dummy;
		//  bidir_decode_search(vt, dummy, vme);
		bidir_decode_beam(*sen, dummy, vme);
		for (size_t f = 0; f < sen->size(); f++) {
			sen->at(f).pos = sen->at(f).prd;
		}
		bidir_chuning_decode_beam(*sen, vme_chunking);

		for(int i=0;i<begin.size();i++)
		{
//			///////////////////
//			for(int k=begin[i];k<end[i];k++)
//				cout<<sen->at(k).str<<" ";
//			cout<<ne[i]<<endl;
//			/////////////////////
			if(ne[i].compare("O")!=0)
			{
				result.push_back(NER_mesample(ne[i],*sen,begin[i],end[i]));
				if(begin[i]>1&&end[i]<sen->size()-1)
				{
					result.push_back(NER_mesample("O",*sen,begin[i]-1,end[i]));
					result.push_back(NER_mesample("O",*sen,begin[i]-2,end[i]));
					result.push_back(NER_mesample("O",*sen,begin[i],end[i]+1));
					result.push_back(NER_mesample("O",*sen,begin[i],end[i]+2));
				}
				if((end[i]-begin[i])>2)
				{
					result.push_back(NER_mesample("O",*sen,begin[i]+1,end[i]));
					result.push_back(NER_mesample("O",*sen,begin[i]+2,end[i]));
					result.push_back(NER_mesample("O",*sen,begin[i],end[i]-1));
					result.push_back(NER_mesample("O",*sen,begin[i],end[i]-2));
				}
			}
		}
		bool *candidates=new bool[sen->size()+1];
		for(int i=0;i<sen->size()+1;i++)candidates[i]=false;
		for(int i=0;i<sen->size();i++)
			for(int j=i+1;j<=sen->size();j++)
			{
				if(call_is_candidate(*sen,i,j)){for(int p=i;p<=j;p++){candidates[p]=true;}}
			}
		for(int i=0;i<sen->size();i++)
		{
			if(candidates[i])
			{
				int j;
				int start=i;
				for( j=i+1;j<sen->size()&&candidates[j];i++,j++);
//				for(int p=start;p<j;p++)cout<<sen->at(p).str<<" ";
//				cout<<endl;
				bool belongtoO=true;
				for(int p=0;p<begin.size();p++)if(begin[p]==start&&end[p]==j){belongtoO=false;break;}
				if(belongtoO){
									for(int p=start;p<j;p++)cout<<sen->at(p).str<<" ";
									cout<<endl;
				}
					//result.push_back(NER_mesample("O",*sen,start,j));}
			}
		}
		delete []candidates;
		abstract.push_back(sen);
	}
	return result;

}


int article::readrfomXMl(pugi::xml_node article)
{
	string raw_id=article.child("articleinfo").child("bibliomisc").text().as_string();
	PumbedID=raw_id.substr(raw_id.find_first_of(':')+1,raw_id.size()-raw_id.find_first_of(':')-1);
	pugi::xml_node title=article.child("title");
	string con="cons";
	abstract.clear();
	article.child("abstract").append_copy(title.child("sentence"));
	for(pugi::xml_node sentence=article.child("abstract").child("sentence");sentence;sentence=sentence.next_sibling())
	{
		Sentence* sen=new Sentence();
		for(pugi::xml_node token=sentence.first_child();token;token=token.next_sibling())
		{
			//		cout<<token.name()<<endl;
			if(con.compare(token.name())==0)
			{
				Sentence temp=get_Sentence_from_cons(token);
				for(int i=0;i<temp.size();i++)
				{
					sen->push_back(temp[i]);
				}
			}
			else
			{
				//cout<<token.text().as_string()<<endl;
				tokenizeSentence(token.text().as_string(),sen,"O");
			}
		}
		abstract.push_back(sen);
	}
	//	writetoXml("");
}


void article::PrintAbstract()
{
	int j=0;
	Sentence *s;
	cout<<this->PumbedID<<endl;
	for(int i=0;i<abstract.size();i++)
	{
		s=abstract.at(i);
		while(j<s->size())
		{
			cout<<s->at(j).str<<" ";
			j++;
		}
		cout<<endl<<endl;

		j=0;
	}

}



//////////////////////////////////////////////////////////////////////////////
int article::downloadpapers(string query,int noPapers,string Outputpath)
{
	string cmd="perl getIds.pl "+Outputpath+" "+intToString(noPapers)+" "+query;

	getStdoutFromCommand(cmd);
	//getStdoutFromCommand6("rm "+Outputpath+"Temp_id.txt");
	return 0;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
vector<Sentence*> article::getAbstract() const
{
	return abstract;
}
string article::getAffilation() const
{
	return affilation;
}
string article::getAuthors() const
{
	return authors;
}
string article::getPumbedId() const
{
	return PumbedID;
}
double article::getScore() const
{
	return score;
}
string article::getTitle() const
{
	return title;
}
int article::getYear() const
{
	return year;
}
void article::setAbstract(vector<Sentence*> abstract)
{
	this->abstract = abstract;
}
void article::setAffilation(string affilation)
{
	this->affilation = affilation;
}
void article::setAuthors(string authors)
{
	this->authors = authors;
}
void article::setPumbedId(string PumbedID)
{
	this->PumbedID = PumbedID;
}
void article::setScore(double score)
{
	this->score = score;
}
void article::setTitle(string title)
{
	this->title = title;
}
void article::setYear(int year)
{
	this->year = year;
}
article::~article() {
	// TODO Auto-generated destructor stub
	this->PumbedID.erase(0,this->PumbedID.size());
	this->affilation.erase(0,this->affilation.size());
	this->authors.erase(0,this->authors.size());
	this->title.erase(0,this->title.size());

	for(int i=0;i<abstract.size();i++)
	{
		for(int j=0;j<abstract[i]->size();j++)
		{

			//	cout<<abstract.at(i)->at(j).cprd<<endl;
			//cout<<abstract.at(i)->at(j).pos<<endl;
			//		cout<<abstract.at(i)->at(j).prd<<endl;
			//	cout<<abstract.at(i)->at(j).tag<<endl;
			Token* t=&(abstract.at(i)->at(j));
			if(!t->str.empty())
			{
				t->str.erase(0,t->str.length());
			}

			if(&(t->cprd)!=NULL)
				t->cprd.erase(0,t->cprd.length());
			if(&(t->pos)!=NULL)
				t->pos.erase(0,t->pos.length());
			if(&(t->prd)!=NULL)
				t->prd.erase(0,t->prd.length());
			if(&(t->tag)!=NULL)
				t->tag.erase(0,t->tag.length());

			//
			//			if(&(t->str)!=NULL)
			//				delete &t->str;
			//			if(&(t->cprd)!=NULL)
			//				delete &t->cprd;
			//			if(&(t->pos)!=NULL)
			//				delete &t->pos;
			//			if(&(t->prd)!=NULL)
			//				delete &t->prd;
			//			if(&(t->tag)!=NULL)
			//				delete &t->tag;
			//			if(t!=NULL)
			//			delete t;
		}
		abstract[i]->erase(abstract[i]->begin(),abstract[i]->end());
		delete abstract[i];
	}
}

int article::writetoREF(string filepath)
{
	ofstream File((filepath+".ref").c_str(), ios::out|ios::app);
	File<<"###MEDLINE:"<<PumbedID<<endl<<endl;
	for(int i=0;i<abstract.size();i++)
	{
		for(int j=0;j<abstract[i]->size();j++)
			File<<abstract[i]->at(j).str<<"\t"<<abstract[i]->at(j).ne<<endl;
		File<<endl;
	}
	File.close();
}
